package transcoding

import java.io.InputStream
import play.api.libs.iteratee.Enumerator
import com.xuggle.mediatool.ToolFactory
import com.xuggle.xuggler.IContainer
import com.xuggle.xuggler.IContainerFormat
import com.xuggle.xuggler.ICodec
import java.io.FileInputStream
import java.io.File
import play.api.libs.iteratee.Error
import com.xuggle.xuggler.io.XugglerIO
import java.io.ByteArrayOutputStream
import java.io.PipedInputStream
import scala.actors.Actor
import play.api.Logger

object XuggleUtil {

  def test = {
    transcodedStreamOf(new FileInputStream(new File("/home/giacomo/Downloads/Game.of.Thrones.S02E09.HDTV.x264-ASAP.mp4")))
  }

  def transcodedStreamOf(in: InputStream) /*Enumerator[Array[Byte]]*/ = {

    val pin = new PipedInputStream()
    val pout = new java.io.PipedOutputStream(pin)

    val inURL = XugglerIO.map(in)
    val outURL = XugglerIO.map(pout)

    Logger.debug("IN: %s\n OUT: %s".format(inURL, outURL))

    val reader = ToolFactory.makeReader(inURL) //"/home/giacomo/Downloads/Game.of.Thrones.S02E09.HDTV.x264-ASAP.mp4"
    val inFormat = reader.getContainer().getContainerFormat()
    Logger.debug("input format: " + inFormat.getInputFormatShortName())

    val format = IContainerFormat.make()
    //format.establishOutputCodecId(ICodec.ID.CODEC_ID_H264)
    format.setOutputFormat("flv", outURL, "video/x-flv")

    val outContainer = IContainer.make(format)
    val writer = ToolFactory.makeWriter(outURL, reader)
    writer.getContainer().setFormat(format)
    //writer.getContainer().getStream(1).setMetaData()
    reader.addListener(writer)

    val a = new Actor {
      def act() {
        loop {
          react {
            case 'Process =>
              try {
                Logger.debug("Start reading packet")
                Logger.debug("Available from input file stream: %d".format(in.available()))
                //Logger.debug("Read from input file stream: %d".format(in.read()))
                while (reader.readPacket() == null) {
                  Logger.debug("packet read successfully")
                  exit
                }
                Logger.debug("Finished reading packet")
              } catch {
                case e: Throwable =>
                  Logger.debug("Closing output because of error while reading", e)
                  pout.close()
              }
            case 'Interrupt =>
              Logger.debug("Received interrupt, closing streams...")
              in.close()
              pout.close()
              exit
          }
        }
      }
    }

    a.start
    a ! 'Process
    
    try{

    val buffer = new Array[Byte](1024)
    val chunk = pin.read(buffer) match {
      case -1 =>
        Logger.debug("Done reading")
        None
      case read =>
        Logger.debug("received %d bytes".format(read))
        val input = new Array[Byte](read)
        System.arraycopy(buffer, 0, input, 0, read)
        Logger.debug("content: %s".format(input.toString()))
        Some(input)
    }
    }catch{
      case _ => Logger.debug("interrupted")
    }
    
    Logger.debug("Available for output: %d".format(pin.available()))

    a ! 'Interrupt
    in.close()
    pout.close()
    
    Thread sleep 10000

    //Enumerator.fromStream(pin)
  }
}